package com.itheima.reggie.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.reggie.common.R;
import com.itheima.reggie.entity.Category;
import com.itheima.reggie.entity.Dish;
import com.itheima.reggie.entity.DishDto;
import com.itheima.reggie.entity.DishFlavor;
import com.itheima.reggie.service.CategoryService;
import com.itheima.reggie.service.DishFlavorService;
import com.itheima.reggie.service.DishService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;

/**
 * @author ：石破天
 * @date ：Created in 2022年12月20日
 * @description ：
 * @version: 1.0
 */
@Slf4j
@RestController
@RequestMapping("/dish")
@Api(tags = "菜品相关接口")
public class DishController {

    @Autowired
    private DishService dishService;
     //用哪个表 找哪个表的service
    @Autowired
    private CategoryService categoryService;

    @Autowired
    private DishFlavorService dishFlavorService;

    @Autowired
    private RedisTemplate redisTemplate;

    /*
     前端的数据谁类接收呢？
    用dish 接收 接收不到 flavors数据
    flavors接收  接收不到 dish
    尴了个尬！
      专门造一个类  接收 dish全部数据
                  以及接收dish相关的 flavors数据
        DishDto 有 dish基本信息 + 口味列表
     */
    @PostMapping
    @ApiOperation("新增菜品接口")
    public R<String> save(@RequestBody DishDto dishdto){
        log.info("dishdto里面包含菜品基本信息和菜品口味列表信息:{}",dishdto);
        /*
        重写一个方法  保存菜品基本信息的同时保存 相关菜品口味关系信息
        数据来源于 dishdto
         */
        dishService.saveWithFlavor(dishdto);
        // 添加成功 之后 更新  在 redis清理掉 当前分类id下的所有菜品
        String key = "dish_"+dishdto.getCategoryId();//把当前受影响的菜品分类清理掉
        redisTemplate.delete(key);
        return R.success("添加成功");
    }

    /**
     *   分页查询
     * @param page  页码
     * @param pageSize  每页显示条数
     * @param name   模糊查询 的条件  name属性
     * @return
     */
    @GetMapping("/page")
    @ApiOperation("菜品分页查询")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "page",value = "当前页码",required = true),
            @ApiImplicitParam(name = "pageSize",value = "每页显示记录数",required = true),
            @ApiImplicitParam(name = "name",value = "菜品名称",required = false)
    })
    public R<Page> page(int page,int pageSize,String name){
        log.info("进行分页查询：");
        //1:构建 分页构造器  page对象
        Page<Dish> pageInfo = new Page<>(page,pageSize);
        //2:构建 条件构造器 queryWrapper
        LambdaQueryWrapper<Dish> wrapper = new LambdaQueryWrapper<>();
        //3:拼接查询条件
//        if(name!=null && name.length()>0){
//            // ! (name==null || name.length()==0)
//            wrapper.like(Dish::getName,name);
//        }
        //  wrapper.like((name!=null && name.length()>0),Dish::getName,name);
        wrapper.like(StringUtils.isNotEmpty(name),Dish::getName,name);
        // 看起来更高级 其实 跟上面代码一个意思。

        //4:分页查询
        dishService.page(pageInfo,wrapper);
        //R---data属性--pageInfo---records当前记录数据---List<Dish>---Dish里面没有 categoryName属性
        // 所以页面没展示 没错，这样不合适！！！
        // DishDto----List<DishDto>----records---Page<DishDto>
        //  Page<Dish> ===>Page<DishDto>
        // 解决方式 别再返回  Page<Dish>  而去返回 Page<DishDto>
        Page<DishDto> dishDtoPage = new Page<>();
        // 把查询出来的数据 都封装到 dishDtoPage中
//        dishDtoPage.setRecords(pageInfo.getRecords()); x
//          dishDtoPage.setCurrent(pageInfo.getCurrent());√
//          dishDtoPage.setTotal(pageInfo.getTotal());√
//          dishDtoPage.setSize(pageInfo.getSize());√
        // 把 pageInfo 所有属性 对应 赋值给了 dishDtoPage  除了records属性
        BeanUtils.copyProperties(pageInfo,dishDtoPage,"records");

        // 创建一个  List<DishDto> 对象
        List<DishDto> records = new ArrayList<>();
        //
        List<Dish> pageInfoRecords = pageInfo.getRecords();
        //  List<Dish> ===>List<DishDto>
        // 往 records里面 添加 查询出来的dish数据 转换DishDto
         //遍历存在的数据  pageInfoRecords  得到每一个查询出来的dish对象
        for (Dish dish : pageInfoRecords) {
            //创建一个 DishDto
            DishDto dishDto = new DishDto();
           // dish--所有属性 复制给 dishDto
            BeanUtils.copyProperties(dish,dishDto);
            //根据categoryId 查到 Category数据
            Category category = categoryService.getById(dishDto.getCategoryId());
            // dishDto 已经有 dish所有的属性 但是 categoryName
            dishDto.setCategoryName(category.getName());
            // 放到集合中
            records.add(dishDto);
        }
        //最终 records里面 填满了查询的数据
        dishDtoPage.setRecords(records);
        //5:返回分页对象
        return R.success(dishDtoPage);
    }

    //根据id查询 菜品基本信息+口味关联信息
    @GetMapping("/{id}")
    public R<DishDto> echo(@PathVariable Long id){
        log.info("要查询的dishid:"+id);
        // service 去查询
       //  service自带的方法只能查询基本的菜品信息
        // 我们想要基本信息和口味关联信息
        // Dish dish = dishService.getById(id);
        // 自己个 写一个方法 查询基本信息查询关联口味信息
        //  用DishDto接收
        DishDto dishDto = dishService.getByIdWithFlovor(id);
        return R.success(dishDto);
    }

    //更新
    @PutMapping
    public R<String> update(@RequestBody DishDto dishDto){
        log.info("修改后的菜品基本数据+口味关联数据:"+dishDto);
        log.info("修改后的菜品基本数据+口味关联数据:{}",dishDto);

        //找service处理
//        dishService.updateById(dishDto);只能修改一张表 想修改两张
        // 自己写
        dishService.updateByIdWithFlavor(dishDto);
        //清理所有菜品的缓存数据
        Set keys = redisTemplate.keys("dish_*"); //获取所有以dish_xxx开头的key
        // 因为修改的时候 可能把 菜品分类改了
        redisTemplate.delete(keys); //删除这些key

        return R.success("修改菜品相关信息成功");
    }

    // 批量启售和停售
    @PostMapping("/status/{sta}")
    @Transactional
    public R<String> updateStatus(@PathVariable Integer sta,Long[] ids){
        log.info("需要修改状态的id是:"+ Arrays.toString(ids));
        // 修改
        //  根据菜品id 修改对应菜品的状态
      // boolean update(Wrapper<T> updateWrapper);
        /*
           QueryWrapper  理解为  where 后面的条件拼接
           UpdateWrapper
              既可以表示 where后面的拼接条件  eq() like()
              除此之外 还有  设置条件的功能
              update 表名 set 字段1=值1，字段2=值2...where id=1
         */
        // update dish set status=? where id=?
        for (Long id : ids) {
            // update dish set status=? where id=?
            LambdaUpdateWrapper<Dish> wrapper = new LambdaUpdateWrapper<>();
            wrapper.set(Dish::getStatus,sta);// set status=?
//          wrapper.set("status",sta);
            wrapper.eq(Dish::getId,id);
            //执行更新
            dishService.update(wrapper);
        }
//        update dish set status=? where id in ?

        //清理所有菜品的缓存数据
        Set keys = redisTemplate.keys("dish_*"); //获取所有以dish_xxx开头的key
        // 因为修改的时候 可能把 菜品分类改了
        redisTemplate.delete(keys); //删除这些key
        return R.success("批量修改状态成功");
    }



    //根据菜品分类id 查询菜品列表信息
    @GetMapping("/list")
    public R<List<DishDto>> list(Long categoryId,Integer status){

       /*
        先从redis中 查询
            查什么？
                某个"菜品分类"下的！！！菜品的集合
            查到了 就直接返回
            查不到 去数据库中查 存到redis中
        */
        String key = "dish_"+categoryId;//键怎么起名字 dish_川菜分类id  dish_湘菜分类id
        List<DishDto> redisDtoList = (List<DishDto>)redisTemplate.opsForValue().get(key);
         log.info("从redis中取出的集合:"+redisDtoList);
        if(redisDtoList!=null){//redis里有数据
            log.info("菜品数据是从 redis取出来的。。。。不用查询数据库了");
            return R.success(redisDtoList);
        }
        // 如果没查到 去数据库查



        log.info("查看需要查询的菜品分类id:"+categoryId);
        // select * from dish where category_id=? and status=1
        LambdaQueryWrapper<Dish> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Dish::getCategoryId,categoryId);
        //拼一个wrapper条件
        wrapper.eq(status!=null,Dish::getStatus,status);
        List<Dish> dishList = dishService.list(wrapper);
        // dish没有口味信息  前端没有展示 口味
        // 需要返回带口味 dishdto
        List<DishDto> dishDtoList = new ArrayList<>();
        //  List<Dish> dishList===> List<DishDto> dishDtoList
        for (Dish dish : dishList) {
            DishDto dishDto = new DishDto();
            BeanUtils.copyProperties(dish,dishDto);
            //再加入相关的菜品口味数据
            // 根据菜品的id
            Long dishId = dishDto.getId();
            // select * from dish_flavor where dish_id=?
            LambdaQueryWrapper<DishFlavor> wrapper1 = new LambdaQueryWrapper<>();
            wrapper1.eq(DishFlavor::getDishId,dishId);
            List<DishFlavor> flavors = dishFlavorService.list(wrapper1);
            //存到 dishdto中
            dishDto.setFlavors(flavors);
            //存到集合中
            dishDtoList.add(dishDto);
        }
        // redis没数据  查询了数据 得到最后数据  dishDtoList
        // 再把 查到的存到redis中
        redisTemplate.opsForValue().set(key,dishDtoList);

       return R.success(dishDtoList);
    }

}
